local rad = math.rad
local sin = math.sin
local cos = math.cos


local reservedNames = {
	["name"] = true,
	["parent"] = true,
	["offset"] = true,
  ["offsetX"] = true,
	["offsetY"] = true,
	["offsetZ"] = true,
	["rotate"] = true,
	["rotateX"] = true,
	["rotateY"] = true,
	["rotateZ"] = true,
	["scale"] = true,
	["scaleX"] = true,
	["scaleY"] = true,
	["scaleZ"] = true,
	["rel_offset"] = true,
	["angle"] = true,
}

function CalculateLocalOffsets (model)
	local function ProcessPiece (piece, parentX, parentY, parentZ)
		local offset = piece.offset or {}
		local offsetX, offsetY, offsetZ
		if (type(piece.rel_offset) == "table") then
			local rel_offset = piece.rel_offset
			local relX = rel_offset[1] or 0
			local relZ = rel_offset[3] or 0

			if (piece.angle) then
				local angle = rad(piece.angle)
				local angleSin = sin(angle)
				local angleCos = cos(angle)

				local newX = relX * angleCos - relZ * angleSin;
				      relZ = relX * angleSin + relZ * angleCos;
				relX = newX
				piece.angle = nil
			end

			offsetX = parentX + relX
			offsetY = parentY + (rel_offset[2] or 0)
			offsetZ = parentZ + relZ
			piece.rel_offset = nil
		else
			offsetX = offset[1] or 0
			offsetY = offset[2] or 0
			offsetZ = offset[3] or 0
		end

		for n, p in pairs(piece) do
			if (reservedNames[n] ~= true) then
				ProcessPiece (p, offsetX, offsetY, offsetZ)
			end
		end

		offset[1] = offsetX - parentX
		offset[2] = offsetY - parentY
		offset[3] = offsetZ - parentZ
		piece.offset = offset
	end

	for _, p in pairs(model.pieces) do
		ProcessPiece (p, 0, 0, 0)
	end
end


function ConvertPiecesTree (model)
  local modelPieces = model.pieces
  
	local function ProcessPiece (name, piece)
    for n, p in pairs(piece) do
      if (reservedNames[n] ~= true) then
        if (type(p) == "table") then
          p.parent = p.parent or name
          modelPieces[n] = p
          ProcessPiece (n, p)
        end     
        piece[n] = nil
      end  
    end
  end

	for n, p in pairs(modelPieces) do
		ProcessPiece (n, p)
	end
end